/**
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2008，所有权利保留。
 * 
 * 项目名：	rumba
 * 文件名：	GWTModuleDefLoader.java
 * 模块说明：	
 * 修改历史：
 * Feb 13, 2008 - lxm - 创建。
 */
package com.hd123.rumba.request;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.hd123.rumba.exception.BusinessException;
import com.hd123.rumba.util.XMLUtil;

/**
 * gwt模块定义信息载入器。
 * <p>
 * 
 * 其中提供了一个缓冲器，以避免频繁的对.gwt.xml的解析。
 * 
 * @author lxm
 * 
 */
class GWTModuleDefLoader {

  /**
   * 载入一个指定模块定义信息。
   * 
   * @param moduleName
   *          指定模块名。
   * @return 返回对应的模块定义信息。
   * @throws BusinessException
   */
  public static GWTModuleDef load(String moduleName) throws BusinessException {
    return doLoad(moduleName);
  }

  /** 缓冲区 */
  private static Map<String, GWTModuleDef> buffer = new HashMap();

  private static GWTModuleDef doLoad(String moduleName) throws BusinessException {
    // 检查缓冲区
    GWTModuleDef moduleDef = buffer.get(moduleName);
    if (moduleDef != null)
      return moduleDef;

    moduleDef = new GWTModuleDef();

    // 取得对应模块定义文件。
    Document doc;
    try {
      String fileName = "/" + moduleName.replace('.', '/') + ".gwt.xml";
      InputStream in = GWTModuleDefLoader.class.getResourceAsStream(fileName);
      if (in == null) {
        buffer.put(moduleName, moduleDef);
        return moduleDef;
      }
      doc = XMLUtil.parse(in);
    } catch (BusinessException e) {
      throw new BusinessException("无找到指定模块的定义信息。\n" + e.getMessage());
    }

    List<Element> eModuleList = XMLUtil.getChildElementsByTagName(doc, "module");
    if (eModuleList.size() == 0)
      throw new BusinessException("无法正确解析GWT模块文件：" + moduleName);
    Element eModule = eModuleList.get(0);

    // 解析<inherits>
    List<Element> eInheritsList = XMLUtil.getChildElementsByTagName(eModule, "inherits");
    for (Element eInherits : eInheritsList) {
      String name = XMLUtil.readString(eInherits, "name");
      GWTModuleDef inheritedModuleDef = doLoad(name);
      moduleDef.merge(inheritedModuleDef);
    }

    // 解析<public>
    List<Element> ePublicList = XMLUtil.getChildElementsByTagName(eModule, "public");
    if (ePublicList.size() > 0) {
      Element ePublic = ePublicList.get(0);
      String path = XMLUtil.readString(ePublic, "path");
      if (path != null)
        moduleDef.setPublicPath(path);
    }
    
    // 解析<servlet>
    List<Element> eServletList = XMLUtil.getChildElementsByTagName(eModule, "servlet");
    for (Element eServlet : eServletList) {
      String path = XMLUtil.readString(eServlet, "path");
      String clazz = XMLUtil.readString(eServlet, "class");
      moduleDef.getServlets().put(path, clazz);
    }

    buffer.put(moduleName, moduleDef);
    return moduleDef;
  }
}
